<html>
 <head>
  <meta charset="UTF-8">
 </head>
 <body>
  <h1 data-lake-id="lwa4K" id="lwa4K"><span data-lake-id="u84422374" id="u84422374">典型回答</span></h1>
  <p data-lake-id="ue94518c2" id="ue94518c2"><br></p>
  <p data-lake-id="uf3de134e" id="uf3de134e"><span data-lake-id="uf3540ecb" id="uf3540ecb">Zuul是一个开源的网关服务，主要用于将客户端请求路由到相应的微服务实例。它是Netflix公司开发的，现在成为了Spring Cloud生态系统中的一部分。</span></p>
  <p data-lake-id="u7ff4d0a8" id="u7ff4d0a8"><span data-lake-id="ud2166cf1" id="ud2166cf1">​</span><br></p>
  <p data-lake-id="u44835e73" id="u44835e73"><span data-lake-id="u4ae83324" id="u4ae83324">网关就相当于是一个前置的入口，所有的请求都要经过他，然后通过它进行服务转发和路由。</span></p>
  <p data-lake-id="u624582f2" id="u624582f2"><span data-lake-id="u01718f25" id="u01718f25">​</span><br></p>
  <p data-lake-id="uab64eed3" id="uab64eed3"><img src="https://cdn.nlark.com/yuque/0/2023/png/5378072/1681548771739-ceb1ed3e-47f0-49bb-9dc0-3903123033db.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_47%2Ctext_SmF2YSA4IEd1IFA%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10"></p>
  <p data-lake-id="u1cc02ad2" id="u1cc02ad2"><br></p>
  <p data-lake-id="u6758ef2b" id="u6758ef2b"><br></p>
  <p data-lake-id="ucc501712" id="ucc501712"><span data-lake-id="u2ecd7b40" id="u2ecd7b40">网关能带来几个好处，首先比较容易想到的就是他承担了统一的入口和出口的角色，所有的请求都需要经过他，那么他就可以很方便的管理这些服务。</span></p>
  <p data-lake-id="ue1c5de7b" id="ue1c5de7b"><span data-lake-id="ub3c4dca4" id="ub3c4dca4">​</span><br></p>
  <p data-lake-id="u982e86d9" id="u982e86d9"><span data-lake-id="uc4396cc6" id="uc4396cc6">其次，因为所有请求都要经过他， 所以他可以做</span><strong><span data-lake-id="u71e5ef57" id="u71e5ef57">负载均衡</span></strong><span data-lake-id="u5d5ba82a" id="u5d5ba82a">以及</span><strong><span data-lake-id="u324826a1" id="u324826a1">动态路由</span></strong><span data-lake-id="ub194ec8d" id="ub194ec8d">。根据不同的负载均衡算法，或者根据请求的参数内容，进行决策选择一个合适的后端服务进行调用。</span></p>
  <p data-lake-id="u472d2793" id="u472d2793"><span data-lake-id="ua13e17e6" id="ua13e17e6">​</span><br></p>
  <p data-lake-id="u2350cf16" id="u2350cf16"><span data-lake-id="u40e6c0ed" id="u40e6c0ed">其他他还有把很多公共的服务集成进来，比如做统一的鉴权、统一的异常处理等，还可以做各种粒度的限流、降级和熔断的操作。</span></p>
  <p data-lake-id="uc527a3ff" id="uc527a3ff"><span data-lake-id="udf0b7b51" id="udf0b7b51">​</span><br></p>
  <h1 data-lake-id="YR5pI" id="YR5pI"><span data-lake-id="u53f2645d" id="u53f2645d">扩展知识</span></h1>
  <p data-lake-id="u2cc43477" id="u2cc43477"><br></p>
  <h2 data-lake-id="Bww6O" id="Bww6O"><span data-lake-id="ud5f321a0" id="ud5f321a0">示例</span></h2>
  <p data-lake-id="u8a8a1948" id="u8a8a1948"><br></p>
  <p data-lake-id="u6474b8b9" id="u6474b8b9"><span data-lake-id="u8a4a16b5" id="u8a4a16b5">以一个简单的示例为例，假设我们有两个服务，一个是 User Service，一个是 Order Service，它们的访问地址分别是：</span></p>
  <p data-lake-id="u11c3ff95" id="u11c3ff95"><span data-lake-id="u221b21e9" id="u221b21e9">​</span><br></p>
  <ul list="u0a6971ad">
   <li fid="uc7aa80a7" data-lake-id="u7bc8a7a8" id="u7bc8a7a8"><span data-lake-id="u9a23f367" id="u9a23f367"> </span><span data-lake-id="uec710693" id="uec710693">http://localhost:8081/user</span></li>
   <li fid="uc7aa80a7" data-lake-id="u5e1190d5" id="u5e1190d5"><span data-lake-id="uebaf14f8" id="uebaf14f8"> </span><span data-lake-id="u2188dd11" id="u2188dd11">http://localhost:8082/order</span></li>
  </ul>
  <p data-lake-id="u2666dc49" id="u2666dc49"><br></p>
  <p data-lake-id="u7ba0e524" id="u7ba0e524"><span data-lake-id="u13fd9158" id="u13fd9158">我们可以在注册中心注册一个 Zuul 服务，然后在 Zuul 服务中配置路由规则，将不同的请求路由给不同的服务：</span></p>
  <p data-lake-id="u16cc211f" id="u16cc211f"><span data-lake-id="u9fb6d226" id="u9fb6d226">​</span><br></p>
  <pre lang="java"><code>
# application.yml

spring:
  application:
    name: api-gateway

zuul:
  routes:
    user-service:
      path: /user/**
      url: http://localhost:8081/user
    order-service:
      path: /order/**
      url: http://localhost:8082/order

</code></pre>
  <p data-lake-id="u85dc38c8" id="u85dc38c8"><br></p>
  <p data-lake-id="ub7e1c4cd" id="ub7e1c4cd"><span data-lake-id="u324e5d26" id="u324e5d26">这样，我们就可以通过访问 http://localhost:8080/user/xxx 来访问 User Service，通过访问 http://localhost:8080/order/xxx 来访问 Order Service 。</span></p>
  <p data-lake-id="u6040d8b8" id="u6040d8b8"><span data-lake-id="u4c2bf4c7" id="u4c2bf4c7">​</span><br></p>
  <p data-lake-id="u4f4dd16e" id="u4f4dd16e"><span data-lake-id="ude818703" id="ude818703">至于前面说的一些鉴权， 限流等，可以通过ZuulFilter来实现，这个是Zuul中的一个组件，用于实现请求拦截和过滤。</span></p>
  <p data-lake-id="u89406fb4" id="u89406fb4"><span data-lake-id="ubd7680da" id="ubd7680da">​</span><br></p>
  <p data-lake-id="u15838b44" id="u15838b44"><span data-lake-id="ua7dab457" id="ua7dab457">比如使用RateLimiter实现一个简单的限流：</span></p>
  <p data-lake-id="u49e9f547" id="u49e9f547"><span data-lake-id="u64689951" id="u64689951">​</span><br></p>
  <pre lang="java"><code>
@Component
public class RateLimitFilter extends ZuulFilter {

    private static final RateLimiter RATE_LIMITER = RateLimiter.create(10);

    @Override
    public String filterType() {
        return "pre";
    }

    @Override
    public int filterOrder() {
        return 0;
    }

    @Override
    public boolean shouldFilter() {
        return true;
    }

    @Override
    public Object run() throws ZuulException {
        if (!RATE_LIMITER.tryAcquire()) {
            throw new ZuulException("Too many requests", HttpStatus.TOO_MANY_REQUESTS.value(), "Rate limit exceeded");
        }
        return null;
    }
}

</code></pre>
  <p data-lake-id="u7021b506" id="u7021b506"><span data-lake-id="u834aa1d9" id="u834aa1d9">​</span><br></p>
  <p data-lake-id="u4860e27e" id="u4860e27e"><span data-lake-id="u3fc7bae1" id="u3fc7bae1">​</span><br></p>
 </body>
</html>